home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / fchart / fgraf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-05  |  22.7 KB  |  842 lines

  1. /*
  2.  *
  3.  *  Fchart  --  fgraf.c
  4.  *
  5.  *  Copyright (C) 1990 Piotr Filip Sawicki
  6.  *
  7.  *  WARNING:
  8.  *    Included "fstyles.i" is an older version of already rewritten graphics
  9.  *    module. Please, don't change anything, rather mail me suggestions.
  10.  *    It emerged like a ball of mud -- don't be shocked with this code.
  11.  *    Writing program I jjust have been adding here new styles, parameters,
  12.  *    bells and whistles -- so it looks like it looks.
  13.  *
  14.  *  Rest of the code can be freely modified and used, as long as this message
  15.  *  is retained and modified code is not redistributed.
  16.  *
  17.  *  Please e-mail any useful additions to fs@uwasa.fi so they may be
  18.  *  included in later releases.
  19.  *
  20.  *  This file should be edited with 4-column tabs!  (:set ts=4 sw=4 in vi)
  21.  */
  22.  
  23. #include <stdio.h>
  24. #include <math.h>
  25. #include "plot.h"
  26. #include "fchart.h"
  27.  
  28. /***********************************************************************/
  29.  
  30. #define MARGIN 0.95            /* margin within frame */
  31.  
  32. /***********************************************************************/
  33.   
  34.  
  35. char *strcpy(),*strncpy(),*strcat(),*sprintf();    /* for lint only */
  36.  
  37. char *make_labl();
  38.  
  39. extern BOOLEAN autoscale;
  40. extern FILE *outfile;
  41. extern BOOLEAN log_y;
  42. extern int term;
  43. extern BOOLEAN draw_border;
  44.  
  45. extern BOOLEAN screen_ok;
  46. extern BOOLEAN term_init;
  47.  
  48. extern double loff,roff,toff,boff;
  49. extern double zero;
  50.  
  51. extern enum GRAV_DIR   gravity, explode;
  52. extern int             samples;
  53. extern double          base;
  54. extern BOOLEAN         p_clockwise, b_clockwise;
  55. extern double          radexp, treshold;
  56. extern double          b_wid, b_spc, b_int;
  57. extern char            thrname[];
  58.  
  59. extern float           xsize, ysize;
  60.  
  61. extern char tic_form[];
  62.  
  63. extern enum FONT_STYLE vect_font;
  64.     
  65. extern struct termentry term_tbl[];
  66. extern struct dfile data_head;    /* static head of data list */
  67.  
  68. extern struct label_def *first_label;    /* defined in flblarr.c */
  69. extern struct linearrow_def *first_arrow;    /* defined in flblarr.c */
  70.  
  71. #ifndef toascii
  72. #define toascii(A) (((int)(A)) & 0x7F)
  73. #endif
  74.  
  75. #define SIGN(A) (A>=0 ? 1 : -1)
  76.  
  77. extern struct Char trt[];    /* font translation table */
  78.  
  79. static struct termentry *t;                /* faster */
  80. static int xbase, ybase, xmaxp, ymaxp;    /* viewport */
  81. static struct xptr *across;                /* used for xplot */
  82. static int first_element;                /* first element for autolabeling */
  83. static BOOLEAN trotate;                    /* whether terminal can rotate text or not */
  84. static int tstate;                        /* state of terminal text rotation */
  85. static int howmuch;                        /* how much space takes as text the longest used value */
  86.  
  87. do_plot(xplot,style,fel)
  88. BOOLEAN xplot;
  89. enum DRAW_STYLE style;
  90. int fel;
  91. {
  92.     /**This bloody part of code initializes graphic *
  93.      * environment, draws borders, outputs trailer, *
  94.      * etc. Before calling drawing fuctions it cal- *
  95.      * culates  viewport  (see toff,boff,roff,loff) *
  96.      * and some other variables used in any style.  *
  97.      *   Ough,  how I long to Pascal's nested local *
  98.      * procedures !!!                               */
  99.  
  100.     BOOLEAN dolabel = (data_head.fname != (char *)NULL);
  101.     int effect, x, y, x0, dx, y0, dy;
  102.     struct label_def *lb;
  103.     struct linearrow_def *ar;
  104.     
  105.     t = &term_tbl[term];
  106.     if (!(*t->scale)(xsize, ysize)) {
  107.         x = t->xmax * xsize;
  108.         y = t->ymax * ysize;
  109.     }
  110.     else {
  111.         x = t->xmax;
  112.         y = t->ymax;
  113.     }
  114.     
  115.     y0 = ybase = (int) ((boff>1.0 ? boff/100.0 : boff)*y) + 1;
  116.     dy = ymaxp = (int) ((1.0-(toff>1.0 ? toff/100.0 : toff))*(y-2)) - (dolabel ? 3*t->v_char : 0);
  117.     if (ymaxp <= ybase)
  118.         int_error("no space to put title, change offsets", NO_CARET);
  119.     x0 = xbase = (int) ((loff>1.0 ? loff/100.0 : loff)*x) + 1;
  120.     dx = xmaxp = (int) ((1.0-(roff>1.0 ? roff/100.0 : roff))*(x-2));
  121.  
  122.     across = (struct xptr *) data_head.data;
  123.     first_element = fel;
  124.     
  125.     if (!term_init) {
  126.         (*t->init)();
  127.         term_init = TRUE;
  128.     }
  129.     screen_ok = FALSE;
  130.     (*t->graphics)();
  131.     trotate = (*t->text_angle)(0);        /* mostly harmless */
  132.     tstate  = 0;
  133.  
  134.     switch (style) {
  135.         case ABARS    : effect = dr_abar(xplot);
  136.             break;
  137.         case SBAR     : effect = dr_sbar(xplot);
  138.             break;
  139.         case LAYB     : effect = dr_lbar(xplot);
  140.             break;
  141.         case PIECHART : effect = dr_pies(xplot);
  142.             break;
  143.         default :
  144.             (*t->text)();
  145.             (void) fflush(outfile);
  146.             int_error("style not yet implemented",NO_CARET);
  147.     }
  148.  
  149.     if (!effect) {
  150.         (*t->text)();
  151.         (void) fflush(outfile);
  152.         int_error("too many data to make sensible picture", NO_CARET);
  153.     }
  154.     
  155.     (*t->linetype)(-2); /* border linetype */
  156.     if (draw_border) {    /* draw plot border */
  157.         (*t->move)(0,0);    
  158.         (*t->vector)(x-1,0);    
  159.         (*t->vector)(x-1,y-1);    
  160.         (*t->vector)(0,y-1);    
  161.         (*t->vector)(0,0);
  162.     }
  163.  
  164.     (*t->linetype)(0);    /* only one guaranted to be solid */
  165.     if (dolabel)        /* put title */
  166.         put_txt((x0+dx)/2, (int)(dy+3*t->v_char/2), data_head.fname, CENTRE, 0);
  167.  
  168.     for (lb=first_label; lb; lb=lb->next) {        /* process and put labels */
  169.         double c_x = lb->x <= 1.0 ? lb->x : lb->x/RESOLUTION;
  170.         double c_y = lb->y <= 1.0 ? lb->y : lb->y/RESOLUTION;
  171.         double c_h = lb->h <= 1.0 ? lb->h : lb->h/RESOLUTION;
  172.         double c_w = lb->w <= 1.0 ? lb->w : lb->w/RESOLUTION;
  173.         int lx, ly, r_x, r_y, r0x, r0y;
  174.         if (!*lb->text)
  175.             continue;
  176.  
  177.         if (lb->paged) {
  178.             r0x =  r0y   = 0;
  179.             r_x = x; r_y = y;
  180.         }
  181.         else {
  182.             r0x = x0;    r0y = y0;
  183.             r_x = dx-x0; r_y = dy-y0;
  184.         }
  185.         lx = r0x + c_x*r_x;
  186.         ly = r0y + c_y*r_y;
  187.  
  188.         if ((lb->rot == L_NORMAL || lb->rot == L_BOTTOM) &&
  189.             !lb->h && !lb->w)                    /* try to put it as a normal text */
  190.             put_txt(lx, ly, lb->text, lb->pos, lb->rot==L_NORMAL ? 0 : 1);
  191.         else {
  192.             double an = (int)lb->rot * Pi/2;
  193.             if (!lb->h && !lb->w)                /* use standard size */
  194.                 (void) draw_text(lx, ly, lb->text, (int)t->v_char, 0, -1, lb->pos, lb->rot==L_RANDOM ? lb->a : an);
  195.             else                                /* draw_text will worry */
  196.                 (void) draw_text(lx, ly, lb->text, (int)(c_h*r_y), (int)(c_w*r_x),
  197.                           -1, lb->pos, lb->rot==L_RANDOM ? lb->a : an);
  198.         }
  199.     }
  200.  
  201.     for (ar=first_arrow; ar; ar=ar->next) {        /* process and put arrows/lines */
  202.         double c_sx = ar->sx <= 1.0 ? ar->sx : ar->sx/RESOLUTION;
  203.         double c_sy = ar->sy <= 1.0 ? ar->sy : ar->sy/RESOLUTION;
  204.         double c_ex = ar->ex <= 1.0 ? ar->ex : ar->ex/RESOLUTION;
  205.         double c_ey = ar->ey <= 1.0 ? ar->ey : ar->ey/RESOLUTION;
  206.         int sx,sy,ex,ey;
  207.         if (ar->startp) {
  208.             sx = x*c_sx;
  209.             sy = y*c_sy;
  210.         }
  211.         else {
  212.             sx = x0 + (dx-x0)*c_sx;
  213.             sy = y0 + (dy-y0)*c_sy;
  214.         }
  215.         if (ar->endp) {
  216.             ex = x*c_ex;
  217.             ey = y*c_ey;
  218.         }
  219.         else {
  220.             ex = x0 + (dx-x0)*c_ex;
  221.             ey = y0 + (dy-y0)*c_ey;
  222.         }
  223.  
  224.         if (ar->arrow)
  225.             (*t->arrow)(sx, sy, ex, ey);
  226.         else {
  227.             (*t->move)(sx, sy);
  228.             (*t->vector)(ex, ey);
  229.         }
  230.     }
  231.             
  232.     (*t->text)();
  233.     (void) fflush(outfile);
  234. }
  235.  
  236. #define MCx(PT,R,AN) nint((PT)+(R)*cos(AN))
  237. #define MCy(PT,R,AN) nint((PT)+(R)*sin(AN))
  238.  
  239. put_arc(x,y,r,a0,da)
  240. int x,y,r;
  241. double a0,da;
  242. /* draw arc from a0, da long */
  243. {
  244.     double step, drto;
  245.     int iter;
  246.  
  247.     (*t->move)(MCx(x,r,a0),MCy(y,r,a0)); 
  248.     step = 2*Pi/samples * (da>0.0 ? 1 : -1);    /* angle step */
  249.     iter = nint(floor(da/step));                /* number of iterations - makes loop faster */
  250.     drto = a0 + step;                            /* next place to draw */
  251.     while (iter--) {
  252.         (*t->vector)(MCx(x,r,drto),MCy(y,r,drto));
  253.         drto += step;
  254.     }
  255.     (*t->vector)(MCx(x,r,a0+da),MCy(y,r,a0+da));    /* last part - prob. shorter */
  256. }
  257.               
  258. put_bar(x0,y0,dx,dy,turn)
  259. int x0,y0,dx,dy,turn;
  260. /* put single bar (opened rectangle) */
  261. {
  262.     if (turn) (*t->move)(x0,y0+dy);
  263.     else {
  264.         (*t->move)(x0,y0);
  265.         (*t->vector)(x0,y0+dy);
  266.     }
  267.     (*t->vector)(x0+dx,y0+dy);
  268.     (*t->vector)(x0+dx,y0);
  269.     if (turn) 
  270.         (*t->vector)(x0,y0);
  271. }
  272.  
  273. BOOLEAN find_ran(min, max, sum, lab)
  274. double *min, *max, *sum;
  275. char **lab;        /* NULL if all labels undefined; "" if labels different; else pointer to the good label */
  276. /**find function used for stacked bars: find min, max and total sum across all data. *
  277.  * Check also possibility of labelling across etc. */
  278. {
  279.     int i;
  280.     vreal w;
  281.     static char nothing[] = "";
  282.     int labfound = 1;
  283.     char *good = NULL, *aux;
  284.     
  285.     *min = VERYLARGE;
  286.     *max = -VERYLARGE;
  287.     *sum = 0.0;
  288.     for (i=0; i<data_head.chunks; i++) {
  289.         if (!across[i].chnp || (w=across[i].chnp->dval[across[i].vindex]) == VERYLARGE) continue;
  290.         if (*min > w) *min = w;
  291.         if (*max < w) *max = w;
  292.         *sum += w;
  293.         if (labfound && across[i].chnp->vlbl && (aux = across[i].chnp->vlbl[across[i].vindex]))
  294.             if (!good)    /* first found */
  295.                 good = aux;
  296.             else
  297.                 labfound = !strcmp(good,aux);
  298.     }
  299.  
  300.     if (!good)            /* no label found, all undefined */
  301.         *lab = NULL;
  302.     else if (labfound)    /* all labels are the same -- return any */
  303.         *lab = good;
  304.     else                 /* different -- return fake label (will be processed in function, but rejected later) */
  305.         *lab = nothing;
  306.     
  307.     if (*min == VERYLARGE || *max == -VERYLARGE)        /* all points undefined */
  308.         return(FALSE);
  309.     else
  310.         return(TRUE);
  311. }
  312.  
  313. char *comm_lget()
  314. /* check labels (like find_ran above), but also advance pointers */
  315. {
  316.     int i, j;
  317.     static char nothing[] = "";
  318.     int labfound = 1;
  319.     char *good = NULL, *aux;
  320.  
  321.     for (i=0; i<data_head.chunks; i++) {
  322.         if (!across[i].chnp) continue;
  323.         j = across[i].vindex;
  324.         if (across[i].chnp->dval[j] != VERYLARGE && across[i].chnp->vlbl && (aux = across[i].chnp->vlbl[j]))
  325.             if (!good)    /* first found */
  326.                 good = aux;
  327.             else
  328.                 labfound = !strcmp(good,aux);
  329.         if (++across[i].vindex == across[i].chnp->used) {
  330.             across[i].chnp = across[i].chnp->next;
  331.             across[i].vindex = 0;
  332.         }
  333.     }
  334.  
  335.     if (!good)        /* no label found, all undefined */
  336.         return (NULL);
  337.     else if (labfound)        /* all labels are the same -- return any */
  338.         return (good);
  339.     else
  340.         return (nothing);
  341. }
  342.     
  343. do_axis(a1,a2,xb,xm,yb,ym,reserved)
  344. double *a1, *a2;
  345. int xb, xm, yb, ym;
  346. BOOLEAN reserved;        /* should we shrink drawing area, or there's enough space ? */
  347. /* draws axis for bars, reserve space for values, put tickmarks with labels */
  348. {
  349.     double minv = *a1, maxv = *a2, tick, minpl, maxpl, unit;
  350.     int dirNS = !((int)gravity&1);
  351.     int i, j, space;
  352.  
  353.     space = dirNS ? (ym-yb)/t->v_char : (xm-xb)/t->h_char;
  354.     if (minv == maxv)
  355.         tick=0;
  356.     else if (log_y) {
  357.         minpl = minv = floor(minv)+log10(2.0)<minv ? floor(minv)+log10(2.0) : floor(minv);
  358.         maxpl = maxv = ceil(maxv)-log10(2.0)>maxv ? ceil(maxv)-log10(2.0) : ceil(maxv);
  359.         tick = floor(log10(maxv-minv))+1;
  360.     }
  361.     else {
  362.         double aux = fabs(minv)>fabs(maxv) ? fabs(minv) : fabs(maxv);
  363.         tick = exp10(floor(log10(aux)));
  364.         aux  = exp10(floor(log10(aux)-1));
  365.         minpl = tick * ceil(minv/tick);
  366.         maxpl = tick * floor(maxv/tick);
  367.         minv = aux * floor(minv/aux);
  368.         maxv = aux * ceil(maxv/aux);
  369.         if ((maxv-minv)/tick <= 3.0) {
  370.             int flip = 1;
  371.             do {
  372.                 tick /= flip ? 2.0 : 5.0;
  373.                 flip = 1-flip;
  374.                 minpl = tick * ceil(minv/tick);
  375.                 maxpl = tick * floor(maxv/tick);
  376.             } while ((maxv-minv)/tick <= 3.0);
  377.         }
  378.         if ((maxpl-minpl)/tick >= (double)space) {
  379.             int flip = 1;
  380.             do {
  381.                 tick *= flip ? 5.0 : 2.0;
  382.                 flip = 1-flip;
  383.                 minpl = tick * ceil(minv/tick);
  384.                 maxpl = tick * floor(maxv/tick);
  385.             } while ((maxpl-minpl)/tick >= (double)space);
  386.         }
  387.     }
  388.  
  389.     if (!tick) return(0);
  390.  
  391.     unit = (dirNS ? ym-yb : xm-xb)/(maxv-minv);
  392.     (*t->linetype)(0);        /* solid linetype */
  393.     switch (gravity) {
  394.         case SOUTH:
  395.             if (!reserved)
  396.                 xb += t->h_char*howmuch + 2*t->h_tic;
  397.             j = xb - 2*t->h_tic;
  398.             (*t->move)(xb,yb);
  399.             (*t->vector)(xb,ym);
  400.             (*t->linetype)(0);        /* the only type solid for sure */
  401.             while (minpl<=maxpl) {
  402.                 (*t->move)(xb,i=yb+nint((minpl-minv)*unit));
  403.                 (*t->vector)(xb-t->h_tic,i);
  404.                 put_txt(j, i, make_labl((double) (log_y ? exp10(minpl) : minpl)), RIGHT, 0);
  405.                 minpl += tick;
  406.             }
  407.             break;
  408.         case NORTH:
  409.             if (!reserved)
  410.                 xm -= t->h_char*howmuch + 2*t->h_tic;
  411.             j = xm + 2*t->h_tic;
  412.             (*t->move)(xm,yb);
  413.             (*t->vector)(xm,ym);
  414.             (*t->linetype)(0);        /* the only type solid for sure */
  415.             while (minpl<=maxpl) {
  416.                 (*t->move)(xm,i=ym-nint((minpl-minv)*unit));
  417.                 (*t->vector)(xm+t->h_tic,i);
  418.                 put_txt(j, i, make_labl((double) (log_y ? exp10(minpl) : minpl)), LEFT, 0);
  419.                 minpl += tick;
  420.             }
  421.             break;
  422.         case WEST:
  423.             if (!reserved)
  424.                 ym -= t->v_char*howmuch + 2*t->v_tic;
  425.             j = ym + 2*t->v_tic;
  426.             (*t->move)(xb,ym);
  427.             (*t->vector)(xm,ym);
  428.             (*t->linetype)(0);        /* the only type solid for sure */
  429.             while (minpl<=maxpl) {
  430.                 (*t->move)(i=xb+nint((minpl-minv)*unit),ym);
  431.                 (*t->vector)(i,ym+t->v_tic);
  432.                 put_txt(i, j, make_labl((double) (log_y ? exp10(minpl) : minpl)), LEFT, 1);
  433.                 minpl += tick;
  434.             }
  435.             break;
  436.         case EAST:
  437.             if (!reserved)
  438.                 yb += t->v_char*howmuch + 2*t->v_tic;
  439.             j = yb - 2*t->v_tic;
  440.             (*t->move)(xm,yb);
  441.             (*t->vector)(xb,yb);
  442.             (*t->linetype)(0);        /* the only type solid for sure */
  443.             while (minpl<=maxpl) {
  444.                 (*t->move)(i=xm-nint((minpl-minv)*unit),yb);
  445.                 (*t->vector)(i,yb-t->v_tic);
  446.                 put_txt(i, j, make_labl((double) (log_y ? exp10(minpl) : minpl)), RIGHT, 1); 
  447.                 minpl += tick;
  448.             }
  449.             break;
  450.     }
  451.  
  452.     *a1 = minv; *a2 = maxv;
  453.     return ( (int) (2*(dirNS ? t->h_tic : t->v_tic) + howmuch*(dirNS ? t->h_char : t->v_char)) );
  454.         /* if (reserved), return value is rejected, so it doesn't matter */
  455. }
  456.  
  457. /* from hereon go different labeling functions. The basic one is the first */
  458.  
  459. int draw_text(x, y, s, h, w, tc, just, an)
  460. int x, y, h, w, tc;
  461. char *s;
  462. enum JUSTIFY just;
  463. double an;
  464. /* draw text in vector font and return useful info - complementary of h parameter */
  465. {
  466.     int wid, k, retv, rwid;
  467.     char *p;
  468.     double sc;
  469.     int *d;
  470.     MATRIX R, S, A;
  471.  
  472.     if (!s || !*s || !tc || !h && !w)
  473.         return(0);        /* nothing useful can be done */
  474.     if (tc>0 && tc < strlen(s))
  475.         s[tc] = '\0';    /* truncate */
  476.     
  477.     for (p=s, wid=0; *p; p++)
  478.         if (!trt[*p=toascii(*p)].wid)
  479.             wid += trt[0].wid + CHAR_OFF;
  480.         else
  481.             wid += trt[*p].wid + CHAR_OFF;
  482.     rwid = wid;
  483.     
  484.     rotat(-an, R);                            /* rotate object system (!) */
  485.     
  486.     if (h) {
  487.         sc = (double)(h) / (double)CHAR_GRD;
  488.         wid *= sc;
  489.         retv = wid;
  490.     }
  491.     else
  492.         wid = 0;
  493.     if (!wid || w && wid > w) {                /* can't with with desired height -- try to schrink */
  494.         sc = (double)(w)/(double)(rwid);
  495.         wid = w;
  496.         retv = CHAR_GRD*sc;                    /* return text height */
  497.     }
  498.     scale(sc, sc, S);
  499.     multi(S, R, A);
  500.     
  501.     switch (just) {
  502.         case LEFT: break;
  503.         case CENTRE: {
  504.             wid /= 2;    /* and no break */
  505.         }
  506.         case RIGHT: {
  507.             x -= (double)wid*cos(an);        /* rotate within coordinate system */
  508.             y -= (double)wid*sin(an);
  509.         }
  510.     }    
  511.     if (x<0 || y<0) 
  512.         return(0);    /* nothing useful - failed */
  513.  
  514. #ifdef NO_ROMAN_FONT
  515.  
  516.     x += (CHAR_OFF/2)*A[0][0]+A[0][2];
  517.     y += (CHAR_OFF/2)*A[1][0]+A[1][2]; 
  518.  
  519. #define MX(v) nint( (*(v))*A[0][0] + (*(v+1))*A[0][1] + A[0][2] )
  520. #define MY(v) nint( (*(v))*A[1][0] + (*(v+1))*A[1][1] + A[1][2] )
  521.  
  522.     {
  523.         unsigned char *u;
  524.         int i,j;
  525.         for ( ; *s; wid=trt[*s].wid, x+=(wid+CHAR_OFF)*A[0][0]+A[0][2], y+=(wid+CHAR_OFF)*A[1][0]+A[1][2], s++) {
  526.             if (!trt[c=*s].wid) c='\0';
  527.             for (i=0; i<3 && (u=trt[c].def[i]); i++) {
  528.                 (*t->move) (x+MX(u), y+MY(u));
  529.                 while (*(u+=2))
  530.                     (*t->vector) (x+MX(u), y+MY(u));
  531.             }
  532.         }
  533.     }
  534.  
  535. #undef MX
  536. #undef MY
  537.  
  538. #else        /* another algorithm: for roman font */
  539.  
  540.     x -= (CHAR_OFF/2)*A[0][0]+A[0][2];
  541.     y -= (CHAR_OFF/2)*A[1][0]+A[1][2]; 
  542.  
  543. #define MX(v) nint( ((v)/100)*A[0][0] + ((v)%100)*A[0][1] + A[0][2] )
  544. #define MY(v) nint( ((v)/100)*A[1][0] + ((v)%100)*A[1][1] + A[1][2] )
  545.  
  546.     for ( ; *s; wid=trt[*s].wid, x+=(wid+CHAR_OFF)*A[0][0]+A[0][2], y+=(wid+CHAR_OFF)*A[1][0]+A[1][2], s++)
  547.         for (d=trt[*s].def; *d; d++)
  548.             if ((k=*d)<0) {
  549.                 k = abs(k);
  550.                 (*t->move)(x+MX(k), y+MY(k));
  551.             }
  552.             else
  553.                 (*t->vector)(x+MX(k), y+MY(k));
  554.     
  555. #undef MX
  556. #undef MY
  557.     
  558. #endif    
  559.  
  560.     return(retv);
  561. }
  562.  
  563. make_just(x, y, j, l, d)
  564. int *x, *y;
  565. int l, d;                /* l != 0 */
  566. enum JUSTIFY j;
  567. /* set terminal justification */
  568. {
  569.     if (!d) { 
  570.         if (j == LEFT) 
  571.             (void) (*t->justify_text)(LEFT);
  572.         else if ((*t->justify_text)(j)) ;
  573.         else if (j == CENTRE)
  574.             *x -= t->h_char * l/2;
  575.         else if (j == RIGHT)
  576.             *x -= t->h_char * l;
  577.         else /* impossible */ return;
  578.     }
  579.     else {
  580.         if (j == LEFT) 
  581.             (void) (*t->justify_text)(LEFT);
  582.         else if ((*t->justify_text)(j)) ;
  583.         else if (j == CENTRE)
  584.             *y -= t->h_char * l/2;
  585.         else if (j == RIGHT)
  586.             *y -= t->h_char * l;
  587.         else /* impossible */ return;
  588.     }
  589. }
  590.  
  591. put_txt(x,y,s,j,d)
  592. int x, y, d;
  593. char *s;
  594. enum JUSTIFY j;
  595. /* put any text on given position, with standard size, sideways or rotated +Pi/2 */
  596. {
  597.     if (!s || !*s) return;
  598.     if ((trotate || !d) && vect_font == F_WHENN ||        /* terminal can or need not rotate */
  599.         vect_font == F_NEVER) {                            /* never use vector font, regardles of anything */
  600.         if (tstate != d)
  601.             (*t->text_angle)(tstate = d);
  602.         make_just(&x, &y, j, strlen(s), d);
  603.         (*t->put_text)(x, y, s);
  604.     }            
  605.     else {        /* use vector font */
  606.         int i = t->v_char;
  607.         if (d)
  608.             x += t->h_char/2;    /* draw_text takes lower-left corner */
  609.         else
  610.             y -= t->h_char/2;
  611.         (void) draw_text(x, y, s, i, 0, -1, j, d*Pi/2);
  612.     }
  613. }
  614.  
  615. put_lab(x,y,s,d,size)
  616. int x, y, d, size;
  617. char *s;
  618. /* put label centered around (x,y), fitting it within given size, use vector font if only allowed */
  619. {
  620.     int i, j, l;
  621.  
  622.     if (!s || !*s || size<=0)
  623.         return;        /* nothing useful */
  624.  
  625.     j = size / t->h_char;                            /* number of standard chars that can fit */
  626.     i = (l=strlen(s)) < howmuch ? howmuch : l;        /* how many chars should we fit ? */
  627.  
  628.     if (vect_font == F_NEVER ||                     /* never use vector font */
  629.         !d && i <= j && vect_font != F_ALWYS) {        /* horizontal, fits within req. size, no need for font */
  630.         if (tstate != d)
  631.             (*t->text_angle)(tstate = d);
  632.         make_just(&x, &y, CENTRE, strlen(s), d);
  633.         (*t->put_text)(x, y, s);
  634.     }
  635.     else {                                            /* pain in the ass */
  636.         if (d)
  637.             x += t->h_char/2;                        /* draw_text takes lower-left corner */
  638.         else
  639.             y -= t->v_char/2;
  640.         i = t->v_char;
  641.         (void) draw_text(x, y, s, i, size, -1, CENTRE, d*Pi/2);
  642.     }
  643. }
  644.  
  645. char *make_labl(d)
  646. double d;
  647. {
  648.     static char buf[200];
  649.     if (d == VERYLARGE || d== -VERYLARGE)
  650.         return(NULL);    /* will be rejected later */
  651.     sprintf(buf, tic_form, (float) d);    /* it's float from user point of view, and compatibility with Gnuplot */
  652.     return(buf);
  653. }
  654.  
  655. set_hm(min, max)
  656. double min, max;
  657. /* find space needed for ticks */
  658. {
  659.     char buf[200];
  660.     int i;
  661.     sprintf(buf, tic_form, (float) min);
  662.     howmuch = strlen(buf);
  663.     sprintf(buf, tic_form, (float) max);
  664.     if (howmuch < (i=strlen(buf)))
  665.         howmuch = i;
  666. }
  667.  
  668. init_acrs()
  669. /* init across pointer structure */
  670. {
  671.     struct dfile *f = &data_head;
  672.     int i = 0;
  673.  
  674.     while (f = f->dnxt) {
  675.         across[i].chnp = f->data;
  676.         across[i++].vindex = 0;
  677.     }
  678. }
  679.  
  680. /* test terminal by drawing border and text */
  681. /* called from command test */
  682. term_test()
  683. /* don't use original test_term() from term.c */
  684. {
  685.     char *str;
  686.     int x,y, xl,yl, i;
  687.     char label[MAX_LINE_LEN];
  688.  
  689.     t = &term_tbl[term];
  690.     if (!term_init) {
  691.        (*t->init)();
  692.        term_init = TRUE;
  693.     }
  694.     screen_ok = FALSE;
  695.     (*t->graphics)();
  696.     /* border linetype */
  697.     (*t->linetype)(-2);
  698.     (*t->move)(0,0);
  699.     (*t->vector)(t->xmax-1,0);
  700.     (*t->vector)(t->xmax-1,t->ymax-1);
  701.     (*t->vector)(0,t->ymax-1);
  702.     (*t->vector)(0,0);
  703.     (void) (*t->justify_text)(LEFT);
  704.     (*t->put_text)(t->h_char*5,t->ymax-t->v_char*3,"Terminal Test");
  705.     (*t->linetype)(0);
  706.     (*t->arrow)(t->h_char*5, t->ymax-t->v_char*5, t->h_char*5, t->ymax/2+t->v_char);
  707.     /* axis linetype */
  708.     (*t->linetype)(-1);
  709.     (*t->move)(t->xmax/2,0);
  710.     (*t->vector)(t->xmax/2,t->ymax-1);
  711.     (*t->move)(0,t->ymax/2);
  712.     (*t->vector)(t->xmax-1,t->ymax/2);
  713.     /* test width and height of characters */
  714.     (*t->linetype)(-2);
  715.     (*t->move)(  t->xmax/2-t->h_char*10,t->ymax/2+t->v_char/2);
  716.     (*t->vector)(t->xmax/2+t->h_char*10,t->ymax/2+t->v_char/2);
  717.     (*t->vector)(t->xmax/2+t->h_char*10,t->ymax/2-t->v_char/2);
  718.     (*t->vector)(t->xmax/2-t->h_char*10,t->ymax/2-t->v_char/2);
  719.     (*t->vector)(t->xmax/2-t->h_char*10,t->ymax/2+t->v_char/2);
  720.     (*t->put_text)(t->xmax/2-t->h_char*10,t->ymax/2,
  721.         "12345678901234567890");
  722.     /* test justification */
  723.     (void) (*t->justify_text)(LEFT);
  724.     (*t->put_text)(t->xmax/2,t->ymax/2+t->v_char*5,"left justified");
  725.     str = "centre+d text";
  726.     if ((*t->justify_text)(CENTRE))
  727.         (*t->put_text)(t->xmax/2,
  728.                 t->ymax/2+t->v_char*4,str);
  729.     else
  730.         (*t->put_text)(t->xmax/2-strlen(str)*t->h_char/2,
  731.                 t->ymax/2+t->v_char*4,str);
  732.     str = "right justified";
  733.     if ((*t->justify_text)(RIGHT))
  734.         (*t->put_text)(t->xmax/2,
  735.                 t->ymax/2+t->v_char*3,str);
  736.     else
  737.         (*t->put_text)(t->xmax/2-strlen(str)*t->h_char,
  738.                 t->ymax/2+t->v_char*3,str);
  739.     /* test text angle */
  740.     str = "rotated ce+ntred text";
  741.     if ((*t->text_angle)(1)) {
  742.         if ((*t->justify_text)(CENTRE))
  743.             (*t->put_text)(t->v_char,
  744.                 t->ymax/2,str);
  745.         else
  746.             (*t->put_text)(t->v_char,
  747.                 t->ymax/2-strlen(str)*t->h_char/2,str);
  748.     }
  749.     else {
  750.         (void) (*t->justify_text)(LEFT);
  751.         (*t->put_text)(t->h_char*2,t->ymax/2-t->v_char*2,"Can't rotate text");
  752.     }
  753.     (void) (*t->justify_text)(LEFT);
  754.     (void) (*t->text_angle)(0);
  755.     /* test tic size */
  756.     (*t->move)(t->xmax/2+t->h_tic*2,0);
  757.     (*t->vector)(t->xmax/2+t->h_tic*2,t->v_tic);
  758.     (*t->move)(t->xmax/2,t->v_tic*2);
  759.     (*t->vector)(t->xmax/2+t->h_tic,t->v_tic*2);
  760.     (*t->put_text)(t->xmax/2+t->h_tic*2,t->v_tic*2+t->v_char/2,"test tics");
  761.     /* test line and point types */
  762.     x = t->xmax - t->h_char*4 - t->h_tic*4;
  763.     y = t->ymax - t->v_char;
  764.     for ( i = -2; y > t->v_char; i++ ) {
  765.         (*t->linetype)(i);
  766.         (void) sprintf(label,"%d",i);
  767.         if ((*t->justify_text)(RIGHT))
  768.             (*t->put_text)(x,y,label);
  769.         else
  770.             (*t->put_text)(x-strlen(label)*t->h_char,y,label);
  771.         (*t->move)(x+t->h_char,y);
  772.         (*t->vector)(x+t->h_char*4,y);
  773.         y -= t->v_char;
  774.     }
  775.     /* test bars */
  776.     (*t->linetype)(-1);
  777.     x = t->xmax/2 + t->xmax/12;
  778.     y = t->ymax/6;
  779.     xl = t->xmax/32;
  780.     yl = t->ymax/32;
  781.     (*t->move)(x,y);
  782.     (*t->vector)(x+xl*6,y);
  783.     x += xl/4;
  784.     for (i=1; i<=4; i++, x+=xl*3/2) {
  785.         (*t->linetype)(i-1);
  786.         put_bar(x,y,xl,i*yl,FALSE);
  787.     }
  788.     /* test pies */
  789.     (*t->linetype)(0);
  790.     x = t->xmax/4;
  791.     y = t->ymax/4;
  792.     i = 3*(t->xmax < t->ymax ? t->xmax : t->ymax)/32;
  793.     xl = MCx(0,i,Pi/4);
  794.     yl = MCy(0,i,Pi/4);
  795.     (*t->move)(x+xl,y+yl);
  796.     (*t->vector)(x-xl,y-yl);
  797.     (*t->move)(x-xl,y+yl);
  798.     (*t->vector)(x+xl,y-yl);
  799.     put_arc(x,y,i,Pi/4,3*Pi/2);
  800.     sprintf(label,"(pie sampling is %d)",samples);
  801.     put_txt(x,y-yl-2*(int)(t->v_char),label,CENTRE,0);
  802.     x += t->xmax/32;
  803.     (*t->move)(x+xl,y-yl);
  804.     (*t->vector)(x,y);
  805.     (*t->vector)(x+xl,y+yl);
  806.     put_arc(x,y,i,Pi/4,-Pi/2);
  807.  
  808.     /* experimental code */
  809.     (*t->linetype)(0);
  810.     x = t->xmax/2 + t->xmax/32;
  811.     y = t->ymax*9/10;
  812.     i = t->v_char;
  813.     x += draw_text(x, y, "experimental", i, 0, -1, LEFT, 0.0);
  814.     i = draw_text(x, y, "scalable", i*2, 0, -1, LEFT, -Pi/4);
  815.     x += i*cos(-Pi/4); y += i*sin(-Pi/4);
  816.     (void) draw_text(x, y, "vector font", 0, (int)(t->xmax/16), -1, LEFT, -Pi/2);
  817.     y -= (int)(t->xmax/16);
  818.     (void) draw_text(x, y, "0123456789", 0, (int)(t->xmax/8), -1, LEFT, -Pi); 
  819.     
  820.     /* and back into text mode */
  821.     (*t->text)();
  822.     (void) fflush(outfile);
  823. }
  824.  
  825.  
  826.  
  827.  
  828.  
  829.  
  830.  
  831.  
  832.  
  833.  
  834. /* included file contains an old version of graphics routines */
  835.  
  836. #include "fstyles.i"
  837.  
  838.  
  839.  
  840.  
  841.  
  842.